#include <stdio.h>
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_spi_flash.h>
#include <esp_spiram.h>
//#include "esp32/spiram.h"
#include "mlx90640/MLX90640_API.h"
#include "console/console.h"
#include "display/dispcolor.h"
#include "adc/adc.h"
#include "save/sd.h"
#include "settings/settings.h"
#include "buttons/buttons.h"
#include "mlx90640/mlx.h"
#include "ui/ui.h"
#include "main.h"

void app_main(void)
{
    printf("Hello world!\n");

    // 显示初始化
    // Инициализация дисплея
    gpio_hold_dis(GPIO_NUM_5);
    dispcolor_Init(dispWidth, dispHeight);

    // Вывод общей информации о CPU
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    console_printf(MsgInfo, "ESP32 rev. %d (%d CPU cores, WiFi%s%s), ", chip_info.revision, chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
    console_printf(MsgInfo, "%d MB %s SPI FLASH\n", spi_flash_get_chip_size() / (1024 * 1024), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
    //console_printf(MsgInfo, "%d MB SPI PSRAM\n", esp_spiram_get_size() / (1024 * 1024));
    console_pause(300);

    // Инициализация АЦП
    init_adc();
    uint32_t BatteryVoltage = getBatteryVoltage();
    console_printf(MsgInfo, "VBAT=%d mV\n", BatteryVoltage);
    console_pause(100);

    Frame = heap_caps_malloc(834 << 1, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
    if (!Frame)
		FatalError("1.Error allocating ram for MLX framebuffer\r\n");
    else
        printf("1.Correctness allocating ram for MLX framebuffer\r\n");

    //缩放、源图像和结果图像的缓冲区
    // Буферы для алгоритмов масштабирования, исходного и итогового изображения
    if (AllocThermoImageBuffers())
    {
        FatalError("Ram allocation error of interpolated thermogram\r\n");// 这一步通不过
        printf("2.Error allocating ram for interpolated thermogram\r\n");
    }
    else
        printf("2.Correctness allocating ram for interpolated thermogram\r\n");

    if (AllocPaletteImageBuffer())
		FatalError("3.Wrong ram allocation for palette\r\n");
    else    
        printf("3.Correctness allocating ram allocation for palette\r\n");

    console_printf(MsgInfo, "SD Card Initialization\r\n");

    // SD初始化
    int initError = 1;
    //int initError = sd_CardInit();// 暂时取消SD卡
    if (!initError)
    {
    	console_printf(MsgInfo, "4.Find SD Card\r\n");

    	uint32_t FreeMb, TotalMb;
    	int8_t err = sd_GetFree(&FreeMb, &TotalMb);
    	if (!err)
        	console_printf(MsgInfo, "Available %d МB Total %d МB\r\n", FreeMb, TotalMb);
    }
    else
    	console_printf(MsgWarning, "4.SD Card Not Found !\r\n");

    // Melexis mlx90640的初始化
    // Инициализация Melexis mlx90640
    MLX90640_Init();

    console_printf(MsgInfo, "5.Read Settings\r\n");
    int err = settings_storage_init();
    settings_read_all();
    if (err)
    	console_printf(MsgWarning, "5.Error Reading Settings !\r\n");
    else
    	console_printf(MsgInfo, "5.Settings Read Successfully\r\n");

    console_printf(MsgInfo, "6.Available Memory:\r\n");
    console_printf(MsgInfo, "6.Internal Memory: %d KB\r\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL) / 1024);
    console_printf(MsgInfo, "6.External Memory: %d KB\r\n", heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / 1024);

    buttons_init();
    console_pause(200);
    printf("7.buttons init ok\r\n");

    console_printf(MsgInfo, "8.Initialization Successfully\r\n");
    console_pause(500);

    dispcolor_SetBrightness(LcdBrightness);

    xTaskCreatePinnedToCore(ui_task, "UI", 6000, NULL, 5, NULL, 0);//6000
    xTaskCreatePinnedToCore(mlx_task, "MLX", 8000, NULL, 5, NULL, 1);
    xTaskCreatePinnedToCore(buttons_task, "BUTTONS", 1024, NULL, 6, NULL, 1);

/*
    for (int i = 10; i >= 0; i--) 
    {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
*/
    int i = 0;
    while (1)
    {
        printf("application running %d seconds...\n", i * 10);
        vTaskDelay(10000 / portTICK_RATE_MS);
        i++;
    }

    printf("Restarting now.\n");
    //fflush(stdout);
    //esp_restart();
}